package com.kerns.generator;

import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.util.RuntimeServicesAware;

/**
 * TODO 代码说明
 *
 * @author kerns
 * @version 1.0
 * @since 2018/5/31
 */
public class VelocityEscapeHtmlOutput implements ReferenceInsertionEventHandler, RuntimeServicesAware {

    private RuntimeServices runtimeServices;

    /**
     * @see org.apache.velocity.app.event.ReferenceInsertionEventHandler#referenceInsert(java.lang.String, java.lang.Object)
     */
    @Override
    public Object referenceInsert(String reference, Object value) {
        if (reference.startsWith("\\$")) {
            return "$";
        }
        return escapeHtml(value);
    }

    /**
     * @see org.apache.velocity.util.RuntimeServicesAware#setRuntimeServices(org.apache.velocity.runtime.RuntimeServices)
     */
    @Override
    public void setRuntimeServices(RuntimeServices rs) {
        this.runtimeServices = rs;
    }

    /**
     * 转义HTML字符串
     *
     * @param str
     * @return
     */
    private static Object escapeHtml(Object value) {
        if (value == null) {
            return null;
        }

        if (!(value instanceof String)) {
            return value;
        }

        String str = value.toString();
        StringBuilder sb = new StringBuilder(str.length() + 30);

        for (int i = 0, len = str.length(); i < len; i++) {
            char c = str.charAt(i);
            // 去除不可见字符
            if ((int) c < 32) {
                continue;
            }

            switch (c) {
                case '<':
                    sb.append("&#60;");
                    break;
                case '>':
                    sb.append("&#62;");
                    break;
                case '&':
                    sb.append("&#38;");
                    break;
                case '"':
                    sb.append("&#34;");
                    break;
                case '\'':
                    sb.append("&#39;");
                    break;
                default:
                    sb.append(c);
                    break;
            }
        }
        str = null;
        return sb.toString();
    }
}
